#include "../include/Dungeon.hh"
#include "../include/Character.hh"
#include "../include/Enemy.hh"
#include "../include/Equipment.hh"
#include "../include/Room.hh"
#include "../include/ShopItem.hh"
#include <iostream>
#include <random>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <numeric>
#include <limits>
#include <thread>
#include <chrono>

#ifdef _WIN32
#define CLEAR "cls"
#else
#define CLEAR "clear"
#endif

#define COLOR_RED "\033[31m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_MAGENTA "\033[35m"
#define COLOR_RESET "\033[0m"
#define COLOR_GRAY "\033[90m"
#define COLOR_GREEN "\033[32m"
#define COLOR_RESET "\033[0m"

using namespace std;

// Structure to track defense buffs/debuffs
struct Buff {
    int value; // Positive for buff, negative for debuff
    int duration; // Remaining turns
    string source; // Source of the effect (e.g., "Heal" or "Shadow Burst")
    bool appliedByPlayer; // true if applied by player, false if applied by enemy
};


Dungeon::Dungeon(int numLayers, int roomsPerLayer, Character* p) 
    : player(p), numLayers(numLayers), currentLayer(1), gold(0) {
    if (!p) {
        throw invalid_argument("Player pointer cannot be null");
    }
    if (roomsPerLayer != 5) {
        cerr << "Warning: Currently, the number of rooms per dungeon layer is fixed at 5.\n";
        roomsPerLayer = 5;
    }
    cout << "Starting to generate dungeon...\n";
    generateDungeon(numLayers, roomsPerLayer);
    cout << "Dungeon generation complete, structure as follows:\n";
    printDungeon();
    selectTalent(*player, 1);
}

void Dungeon::generateDungeon(int numLayers, int roomsPerLayer) {
    random_device rd;
    mt19937 gen(rd());

    layers.resize(numLayers);
    for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex) {
        cout << "Generating Layer " << layerIndex + 1 << "...\n";
        vector<Room> currentLayer;
        currentLayer.emplace_back(1, RoomType::START);
        int rewardRoomIndex = uniform_int_distribution<>(2, roomsPerLayer - 1)(gen);

        for (int i = 2; i <= roomsPerLayer; ++i) {
            if (i == roomsPerLayer) {
                currentLayer.emplace_back(i, RoomType::BOSS);
            } else if (i == rewardRoomIndex) {
                currentLayer.emplace_back(i, RoomType::REWARD);
            } else {
                currentLayer.emplace_back(i, RoomType::ENEMY);
            }
        }

        layers[layerIndex] = std::move(currentLayer); // 使用移动赋值

        for (int i = 0; i < roomsPerLayer; ++i) {
            vector<int> possibleConnections;
            for (int j = 0; j < roomsPerLayer; ++j) {
                if (i != j && layers[layerIndex][i].neighbors.size() < 2 &&
                    find(layers[layerIndex][i].neighbors.begin(), layers[layerIndex][i].neighbors.end(), j + 1) == layers[layerIndex][i].neighbors.end()) {
                    possibleConnections.push_back(j + 1);
                }
            }
            if (!possibleConnections.empty()) {
                shuffle(possibleConnections.begin(), possibleConnections.end(), gen);
                int maxConnections = min(2, (int)possibleConnections.size());
                int numConnections = uniform_int_distribution<>(1, maxConnections)(gen);
                for (int k = 0; k < numConnections; ++k) {
                    int connectTo = possibleConnections[k];
                    if (connectTo >= 1 && connectTo <= roomsPerLayer) {
                        layers[layerIndex][i].neighbors.push_back(connectTo);
                        if (find(layers[layerIndex][connectTo - 1].neighbors.begin(),
                                 layers[layerIndex][connectTo - 1].neighbors.end(), i + 1) == layers[layerIndex][connectTo - 1].neighbors.end()) {
                            layers[layerIndex][connectTo - 1].neighbors.push_back(i + 1);
                        }
                    }
                }
            }
        }

        for (int i = 0; i < roomsPerLayer - 1; ++i) {
            bool connected = false;
            for (int neighbor : layers[layerIndex][i].neighbors) {
                if (neighbor == i + 2 && i + 2 <= roomsPerLayer) {
                    connected = true;
                    break;
                }
            }
            if (!connected && i + 2 <= roomsPerLayer) {
                layers[layerIndex][i].neighbors.push_back(i + 2);
                if (i + 1 < roomsPerLayer &&
                    find(layers[layerIndex][i + 1].neighbors.begin(),
                         layers[layerIndex][i + 1].neighbors.end(), i + 1) == layers[layerIndex][i + 1].neighbors.end()) {
                    layers[layerIndex][i + 1].neighbors.push_back(i + 1);
                }
            }
        }

        if (roomsPerLayer > 1) {
            int bossRoomIndex = roomsPerLayer - 1;
            if (layers[layerIndex][bossRoomIndex].neighbors.empty()) {
                int randomNeighborIndex = uniform_int_distribution<>(0, bossRoomIndex - 1)(gen);
                layers[layerIndex][bossRoomIndex].neighbors.push_back(randomNeighborIndex + 1);
                if (find(layers[layerIndex][randomNeighborIndex].neighbors.begin(),
                         layers[layerIndex][randomNeighborIndex].neighbors.end(), bossRoomIndex + 1) == layers[layerIndex][randomNeighborIndex].neighbors.end()) {
                    layers[layerIndex][randomNeighborIndex].neighbors.push_back(bossRoomIndex + 1);
                }
            }
        }

        for (const auto& room : layers[layerIndex]) {
            for (int neighbor : room.neighbors) {
                if (neighbor < 1 || neighbor > roomsPerLayer) {
                    cerr << "Error: Layer " << layerIndex + 1 << " Room " << room.id << " contains invalid neighbor ID " << neighbor << endl;
                }
            }
        }
    }
}

void Dungeon::printDungeon() const {
    for (size_t layer = 0; layer < layers.size(); ++layer) {
        cout << "Layer " << layer + 1 << ":\n";
        for (const auto& room : layers[layer]) {
            cout << "Room " << room.id << " (" << room.getTypeName() << ")";
            cout << " Connections: ";
            for (int conn : room.neighbors) cout << conn << " ";
            cout << endl;
        }
    }
}

std::unique_ptr<Character> Dungeon::createEnemyForRoom(RoomType type, int& baseGoldDrop, int layer) {
    random_device rd;
    mt19937 gen(rd());
    baseGoldDrop = 0;

    if (type == RoomType::ENEMY) {
        if (layer == 1) {
            if (uniform_int_distribution<>(0, 1)(gen) == 0) {
                cout << "Creating normal enemy - Goblin" << endl;
                baseGoldDrop = 10;
                auto enemy = std::make_unique<Enemy>("Goblin");
                enemy->skills.clear();
                enemy->addSkill(create(SkillType::NormalAttack, layer));
                return enemy;
            } else {
                cout << "Creating normal enemy - Ghost" << endl;
                baseGoldDrop = 15;
                auto enemy = std::make_unique<Ghost>("Ghost");
                enemy->skills.clear();
                enemy->addSkill(create(SkillType::FireBall, layer));
                return enemy;
            }
        } else if (layer == 2) {
            if (uniform_int_distribution<>(0, 1)(gen) == 0) {
                cout << "Creating normal enemy - Armored Warrior" << endl;
                baseGoldDrop = 20;
                auto enemy = std::make_unique<ArmoredWarrior>("Armored Warrior");
                enemy->skills.clear();
                enemy->addSkill(create(SkillType::NormalAttack, layer));
                enemy->addSkill(create(SkillType::IronShield, layer));
                return enemy;
            } else {
                cout << "Creating normal enemy - Golden Devil" << endl;
                baseGoldDrop = 25;
                auto enemy = std::make_unique<GoldenDevil>("Golden Devil");
                enemy->skills.clear();
                enemy->addSkill(create(SkillType::BloodAttack, layer));
                enemy->addSkill(create(SkillType::GoldenStrike, layer));
                return enemy;
            }
        } else if (layer == 3) {
            if (uniform_int_distribution<>(0, 1)(gen) == 0) {
                cout << "Creating normal enemy - Cyborg" << endl;
                baseGoldDrop = 30;
                auto enemy = std::make_unique<Cyborg>("Cyborg");
                enemy->skills.clear();
                enemy->addSkill(create(SkillType::ThunderStrike, layer));
                enemy->addSkill(create(SkillType::OverloadPulse, layer));
                return enemy;
            } else {
                cout << "Creating normal enemy - Explosive Warrior" << endl;
                baseGoldDrop = 35;
                auto enemy = std::make_unique<ExplosiveWarrior>("Explosive Warrior");
                enemy->skills.clear();
                enemy->addSkill(create(SkillType::NormalAttack, layer));
                enemy->addSkill(create(SkillType::ExplosiveBlast, layer));
                return enemy;
            }
        }
    } else if (type == RoomType::BOSS) {
        if (layer == 1) {
            cout << "Creating Boss - Void Lord" << endl;
            baseGoldDrop = 100;
            auto boss = std::make_unique<SuperBoss>("Void Lord");
            boss->skills.clear();
            boss->addSkill(create(SkillType::FireBall, layer));
            boss->addSkill(create(SkillType::Heal, layer));
            boss->addSkill(create(SkillType::DevastatingStrike, layer));
            boss->addSkill(create(SkillType::ThunderStrike, layer));
            boss->addSkill(create(SkillType::ShadowBurst, layer));
            if (boss && !boss->skills.empty()) {
                cout << "Boss skill count: " << boss->skills.size() << endl;
            } else {
                cout << "Error: Boss creation failed or skills are empty" << endl;
            }
            return boss;
        } else if (layer == 2) {
            cout << "Creating Boss - Super Idol" << endl;
            baseGoldDrop = 150;
            auto boss = std::make_unique<SuperIdol>("Super Idol");
            boss->skills.clear();
            boss->addSkill(create(SkillType::JuiceSplash, layer));
            boss->addSkill(create(SkillType::Heal, layer));
            boss->addSkill(create(SkillType::ThunderStrike, layer));
            if (boss && !boss->skills.empty()) {
                cout << "Boss skill count: " << boss->skills.size() << endl;
            } else {
                cout << "Error: Boss creation failed or skills are empty" << endl;
            }
            return boss;
        } else if (layer == 3) {
            cout << "Creating Boss - Demon King" << endl;
            baseGoldDrop = 200;
            auto boss = std::make_unique<DemonKing>("Demon King");
            boss->skills.clear();
            boss->addSkill(create(SkillType::HellfireStorm, layer));
            boss->addSkill(create(SkillType::ShadowBurst, layer));
            boss->addSkill(create(SkillType::BloodAttack, layer));
            boss->addSkill(create(SkillType::DevastatingStrike, layer));
            if (boss && !boss->skills.empty()) {
                cout << "Boss skill count: " << boss->skills.size() << endl;
            } else {
                cout << "Error: Boss creation failed or skills are empty" << endl;
            }
            return boss;
        }
    }
    cout << "No enemy created, returning nullptr" << endl;
    return nullptr;
}

std::unique_ptr<Equipment> Dungeon::createEquipmentDrop(RoomType type, bool isBossDefeated) {
    random_device rd;
    mt19937 gen(rd());
    uniform_real_distribution<> dist(0.0, 1.0);

    if (isBossDefeated) {
        if (currentLayer == 1) {
            if (player->name == "Berserker") {
                return std::make_unique<Equipment>("Void Blade", "Sword of the Void Lord's power, increases attack", EquipmentType::WEAPON, 2);
            } else if (player->name == "Mage") {
                return std::make_unique<Equipment>("Void Staff", "Magic staff of the Void Lord, increases attack", EquipmentType::WEAPON, 2);
            } else if (player->name == "Assassin") {
                return std::make_unique<Equipment>("Void Dagger", "Sharp dagger of the Void Lord, increases attack", EquipmentType::WEAPON, 2);
            }
        } else if (currentLayer == 2) {
            if (player->name == "Berserker") {
                return std::make_unique<Equipment>("Idol Blade", "Sharp blade of the Super Idol, increases attack", EquipmentType::WEAPON, 2);
            } else if (player->name == "Mage") {
                return std::make_unique<Equipment>("Idol Staff", "Magic core of the Super Idol, increases attack", EquipmentType::WEAPON, 2);
            } else if (player->name == "Assassin") {
                return std::make_unique<Equipment>("Idol Dagger", "Swift dagger of the Super Idol, increases attack", EquipmentType::WEAPON, 2);
            }
        } else if (currentLayer == 3) {
            if (player->name == "Berserker") {
                return std::make_unique<Equipment>("Demon Sword", "Destructive sword of the Demon King, increases attack", EquipmentType::WEAPON, 2);
            } else if (player->name == "Mage") {
                return std::make_unique<Equipment>("Demon Staff", "Magic staff of the Demon King, increases attack", EquipmentType::WEAPON, 2);
            } else if (player->name == "Assassin") {
                return std::make_unique<Equipment>("Demon Dagger", "Death dagger of the Demon King, increases attack", EquipmentType::WEAPON, 2);
            }
        }
    }

    if (type == RoomType::ENEMY) {
        if (dist(gen) < 0.5) {
            int equipType = uniform_int_distribution<>(0, 2)(gen);
            switch (equipType) {
                case 0:
                    return std::make_unique<Equipment>("Refined Helmet", "Increases armor and defense", EquipmentType::HELMET, 1);
                case 1:
                    return std::make_unique<Equipment>("Refined Leggings", "Increases armor and defense", EquipmentType::LEGGINGS, 1);
                case 2:
                    return std::make_unique<Equipment>("Refined Boots", "Increases speed", EquipmentType::BOOTS, 1);
            }
        }
    }
    return nullptr;
}

bool Dungeon::isLayerExplored(int layerIndex) const {
    if (layerIndex < 0 || layerIndex >= layers.size()) {
        return false;
    }
    for (const auto& room : layers[layerIndex]) {
        if (room.id <= 4 && !room.visited && room.type != RoomType::REWARD) {
            return false;
        }
    }
    return true;
}

void displayBattleStatus(const Character& player, const Character& enemy) {
    std::cout << "\n--- Battle Status ---" << std::endl;
    std::cout << "Your Information:\n";
    auto bonuses = player.getAttributeBonuses();
    std::cout << "  Health: " << COLOR_RED << player.attributes.health << "/" << player.maxHealth << COLOR_RESET;
    if (bonuses.count("health") && !bonuses.at("health").empty()) {
        std::cout << " (";
        bool first = true;
        for (const auto& bonus : bonuses.at("health")) {
            if (!bonus.isTemporary && bonus.source != "Heal" && bonus.source != "Health Potion" && bonus.source != "Blood Attack") {
                if (!first) std::cout << ", ";
                std::cout << "+" << bonus.value << " " << bonus.source;
                first = false;
            }
        }
        std::cout << ")";
    }
    std::cout << "\n";

    std::cout << "  Attack: " << player.attributes.attack;
    if (bonuses.count("attack") && !bonuses.at("attack").empty()) {
        std::cout << " (";
        bool first = true;
        for (const auto& bonus : bonuses.at("attack")) {
            if (!bonus.isTemporary && bonus.source != "Heal") {
                if (!first) std::cout << ", ";
                std::cout << "+" << bonus.value << " " << bonus.source;
                first = false;
            }
        }
        std::cout << ")";
    }
    std::cout << "\n";

    std::cout << "  Defense: " << player.attributes.defense;
    if (bonuses.count("defense") && !bonuses.at("defense").empty()) {
        std::cout << " (";
        bool first = true;
        for (const auto& bonus : bonuses.at("defense")) {
            if (!bonus.isTemporary && bonus.source != "Heal" && bonus.source != "Iron Shield" && bonus.source != "Golden Slash" && bonus.source != "Hellfire Storm" && bonus.source != "Shadow Burst") {
                if (!first) std::cout << ", ";
                std::cout << "+" << bonus.value << " " << bonus.source;
                first = false;
            }
        }
        std::cout << ")";
    }
    std::cout << "\n";

    std::cout << "  Speed: " << player.attributes.speed;
    if (bonuses.count("speed") && !bonuses.at("speed").empty()) {
        std::cout << " (";
        bool first = true;
        for (const auto& bonus : bonuses.at("speed")) {
            if (!bonus.isTemporary && bonus.source != "Overload Pulse") {
                if (!first) std::cout << ", ";
                std::cout << "+" << bonus.value << " " << bonus.source;
                first = false;
            }
        }
        std::cout << ")";
    }
    std::cout << "\n";

    std::cout << "Enemy Information:\n";
    std::cout << "  Name: " << enemy.name << "\n";
    std::cout << "  Health: " << COLOR_RED << enemy.attributes.health << "/" << enemy.maxHealth << COLOR_RESET << "\n";
    std::cout << "  Attack: " << enemy.attributes.attack << "\n";
    std::cout << "  Defense: " << enemy.attributes.defense << "\n";
    std::cout << "  Speed: " << enemy.attributes.speed << "\n";
}

void Dungeon::selectTalent(Character& player, int layer) {
    random_device rd;
    mt19937 gen(rd());
    const auto& allTalents = Talents::getAllTalents();
    
    if (allTalents.size() < 3) {
        cout << "Error: Insufficient number of talents (at least 3 required)!" << endl;
        return;
    }

    vector<Talent> availableTalents = allTalents;
    shuffle(availableTalents.begin(), availableTalents.end(), gen);
    vector<Talent> talentChoices(availableTalents.begin(), availableTalents.begin() + 3);

    system(CLEAR);
    cout << "=== Select Talent ===\n";
    cout << "Please select a talent to enhance your character: (Talent bonuses increase with layer progression)\n";
    for (size_t i = 0; i < talentChoices.size(); ++i) {
        cout << i + 1 << ". " << talentChoices[i].name << ": " << talentChoices[i].description << "\n";
    }
    cout << "Enter your choice (1-3): ";

    int choice;
    while (!(cin >> choice) || choice < 1 || choice > 3) {
        cout << "Invalid input, please enter a number between 1 and 3: ";
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    const Talent& selectedTalent = talentChoices[choice - 1];
    player.addTalent(selectedTalent, layer);
    cout << "You selected the talent: " << selectedTalent.name << "! The talent has taken effect.\n";
    cout << "Press Enter to continue...\n";
    cin.get();
}

bool Dungeon::fight(Character& player, std::unique_ptr<Character> enemy, int baseGoldDrop) {
    random_device rd;
    mt19937 gen(rd());

    system(CLEAR);
    if (!enemy) {
        cout << "Error: Enemy pointer is null!" << endl;
        return false;
    }
    if (enemy->skills.empty()) {
        cout << "Error: Enemy " << enemy->name << " has no skills!" << endl;
        return false;
    }
    cout << "Starting battle with " << enemy->name << ", skill count: " << enemy->skills.size() << endl;
    cout << "Enemy health: " << enemy->attributes.health << endl;
    if (enemy->name == "Void Lord" || enemy->name == "Super Idol" || enemy->name == "Demon King") {
        cout << "You have entered a BOSS battle room. You must defeat " << enemy->name << " to proceed to the next layer" << endl;
    } else {
        cout << "You have entered a battle room and encountered " << enemy->name << endl;
    }
    this_thread::sleep_for(chrono::seconds(2));

    cout << "\nBattle begins! You are fighting " << enemy->name << "!" << endl;
    player.attributes.damageMultiplier = 1.0f;

    // Structure to track burn effects
    struct BurnEffect {
        int damage; // Health deducted per turn
        int duration; // Remaining turns
        string source; // Source of the effect
    };

    // Structure to track continuous healing effects
    struct HealEffect {
        int amount; // Health restored per turn
        int duration; // Remaining turns
        string source; // Source of the effect
    };

    // Structure to track bleed effects
    struct BleedEffect {
        int damage; // Health deducted per turn
        int duration; // Remaining turns
        string source; // Source of the effect
    };

    std::vector<Buff> playerDefenseBuffs;
    std::vector<Buff> enemyDefenseBuffs;
    std::vector<Buff> playerArmorBuffs;
    std::vector<Buff> enemyArmorBuffs;
    std::vector<BurnEffect> playerBurnEffects;
    std::vector<BurnEffect> enemyBurnEffects;
    std::vector<HealEffect> playerHealEffects;
    std::vector<HealEffect> enemyHealEffects;
    std::vector<BleedEffect> playerBleedEffects;
    std::vector<BleedEffect> enemyBleedEffects;

    while (player.attributes.health > 0 && enemy->attributes.health > 0) {
        system(CLEAR);
        displayBattleStatus(player, *enemy);

        bool playerFirst = player.attributes.speed >= enemy->attributes.speed;

        if (playerFirst) {
            if (player.isStunned) {
                cout << player.name << " is stunned and cannot act!" << endl;
                player.isStunned = false;
                this_thread::sleep_for(chrono::seconds(1));
            } else if (!player.skills.empty()) {
                cout << "\nYour skills:\n";
                for (size_t i = 0; i < player.skills.size(); ++i) {
                    cout << i + 1 << ". " << player.skills[i].name << ": "
                         << player.skills[i].description << "\n";
                }
                cout << "Select a skill (enter number): ";
                int skillChoice;
                while (!(cin >> skillChoice) || skillChoice < 1 || skillChoice > static_cast<int>(player.skills.size())) {
                    cout << "Invalid input, please enter a valid skill number: ";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                }
                if (player.isHealingDisabled && (player.skills[skillChoice - 1].name == "Heal" || player.skills[skillChoice - 1].name == "Haku Technique" || player.skills[skillChoice - 1].name == "Soul Infiltration")) {
                    cout << player.name << "'s healing skills are disabled, this skill is ineffective!" << endl;
                    this_thread::sleep_for(chrono::seconds(1));
                } else {
                    player.skills[skillChoice - 1].use(player, *enemy);
                    if (player.skills[skillChoice - 1].name == "Heal") {
                        playerDefenseBuffs.push_back({5 + (currentLayer - 1) * 2, 2, "Heal", true});
                        player.attributes.defense += 5 + (currentLayer - 1) * 2;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Heal", 5 + (currentLayer - 1) * 2, true});
                    } else if (player.skills[skillChoice - 1].name == "Shadow Burst") {
                        enemyDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 1, "Shadow Burst", true});
                        enemy->attributes.defense -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["defense"].push_back({"Shadow Burst", -(5 + (currentLayer - 1) * 2), true});
                    } else if (player.skills[skillChoice - 1].name == "Iron Shield") {
                        playerDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Iron Shield", true});
                        player.attributes.defense += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Iron Shield", 10 + (currentLayer - 1) * 5, true});
                    } else if (player.skills[skillChoice - 1].name == "Golden Slash") {
                        playerDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Golden Slash", true});
                        player.attributes.critChance += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["critChance"].push_back({"Golden Slash", 10 + (currentLayer - 1) * 5, true});
                    } else if (player.skills[skillChoice - 1].name == "Overload Pulse") {
                        enemyDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 2, "Overload Pulse", true});
                        enemy->attributes.speed -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["speed"].push_back({"Overload Pulse", -(5 + (currentLayer - 1) * 2), true});
                    } else if (player.skills[skillChoice - 1].name == "Juice Splash") {
                        enemyArmorBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Juice Splash", true});
                        enemy->attributes.armor -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["armor"].push_back({"Juice Splash", -(10 + (currentLayer - 1) * 5), true});
                    } else if (player.skills[skillChoice - 1].name == "Hellfire Storm") {
                        enemyDefenseBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Hellfire Storm", true});
                        enemy->attributes.defense -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["defense"].push_back({"Hellfire Storm", -(10 + (currentLayer - 1) * 5), true});
                    } else if (player.skills[skillChoice - 1].name == "Fireball Technique") {
                        int burnDamage = static_cast<int>(enemy->maxHealth * 0.3f);
                        enemyBurnEffects.push_back({burnDamage, 3, "Fireball Technique"});
                    } else if (player.skills[skillChoice - 1].name == "Haku Technique") {
                        int healAmount = static_cast<int>(player.maxHealth * 0.1f);
                        playerHealEffects.push_back({healAmount, 3, "Haku Technique"});
                    } else if (player.skills[skillChoice - 1].name == "Assault Thrust") {
                        enemyArmorBuffs.push_back({-(25 + static_cast<int>(enemy->attributes.armor * 0.3f)), 2, "Assault Thrust", true});
                        enemy->attributes.armor -= (25 + static_cast<int>(enemy->attributes.armor * 0.3f));
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["armor"].push_back({"Assault Thrust", -(25 + static_cast<int>(enemy->attributes.armor * 0.3f)), true});
                    } else if (player.skills[skillChoice - 1].name == "Endless Bleeding") {
                        int bleedDamage = static_cast<int>(enemy->maxHealth * 0.2f);
                        enemyBleedEffects.push_back({bleedDamage, 3, "Endless Bleeding"});
                        enemy->isHealingDisabled = true;
                    } else if (player.skills[skillChoice - 1].name == "Soul Infiltration") {
                        playerDefenseBuffs.push_back({100, 2, "Soul Infiltration", true});
                        player.attributes.critChance += 100;
                        playerDefenseBuffs.push_back({200, 2, "Soul Infiltration", true});
                        player.attributes.critDamage += 200;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["critChance"].push_back({"Soul Infiltration", 100, true});
                        bonuses["critDamage"].push_back({"Soul Infiltration", 200, true});
                    }
                    this_thread::sleep_for(chrono::seconds(1));
                }
            } else {
                cout << "You have no skills! Skipping your turn.\n";
                this_thread::sleep_for(chrono::seconds(1));
            }

            if (enemy->attributes.health <= 0) {
                cout << enemy->name << " has been defeated!" << endl;
                player.onEnemyDefeated();
                break;
            }

            if (enemy->isStunned) {
                cout << enemy->name << " is stunned and cannot act!" << endl;
                enemy->isStunned = false;
                this_thread::sleep_for(chrono::seconds(1));
            } else if (!enemy->skills.empty()) {
                int skillIndex = uniform_int_distribution<>(0, enemy->skills.size() - 1)(gen);
                if (enemy->isHealingDisabled && (enemy->skills[skillIndex].name == "Heal" || enemy->skills[skillIndex].name == "Haku Technique" || enemy->skills[skillIndex].name == "Soul Infiltration")) {
                    cout << enemy->name << "'s healing skills are disabled, this skill is ineffective!" << endl;
                    this_thread::sleep_for(chrono::seconds(1));
                } else {
                    enemy->skills[skillIndex].use(*enemy, player);
                    if (enemy->skills[skillIndex].name == "Shadow Burst") {
                        playerDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 1, "Shadow Burst", false});
                        player.attributes.defense -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Shadow Burst", -(5 + (currentLayer - 1) * 2), true});
                    } else if (enemy->skills[skillIndex].name == "Iron Shield") {
                        enemyDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Iron Shield", false});
                        enemy->attributes.defense += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["defense"].push_back({"Iron Shield", 10 + (currentLayer - 1) * 5, true});
                    } else if (enemy->skills[skillIndex].name == "Golden Slash") {
                        enemyDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Golden Slash", false});
                        enemy->attributes.critChance += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["critChance"].push_back({"Golden Slash", 10 + (currentLayer - 1) * 5, true});
                    } else if (enemy->skills[skillIndex].name == "Overload Pulse") {
                        playerDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 2, "Overload Pulse", false});
                        player.attributes.speed -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["speed"].push_back({"Overload Pulse", -(5 + (currentLayer - 1) * 2), true});
                    } else if (enemy->skills[skillIndex].name == "Juice Splash") {
                        playerArmorBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Juice Splash", false});
                        player.attributes.armor -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["armor"].push_back({"Juice Splash", -(10 + (currentLayer - 1) * 5), true});
                    } else if (enemy->skills[skillIndex].name == "Hellfire Storm") {
                        playerDefenseBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Hellfire Storm", false});
                        player.attributes.defense -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Hellfire Storm", -(10 + (currentLayer - 1) * 5), true});
                    } else if (enemy->skills[skillIndex].name == "Fireball Technique") {
                        int burnDamage = static_cast<int>(player.maxHealth * 0.3f);
                        playerBurnEffects.push_back({burnDamage, 3, "Fireball Technique"});
                    } else if (enemy->skills[skillIndex].name == "Haku Technique") {
                        int healAmount = static_cast<int>(enemy->maxHealth * 0.1f);
                        enemyHealEffects.push_back({healAmount, 3, "Haku Technique"});
                    }
                    this_thread::sleep_for(chrono::seconds(1));
                }
            } else {
                cout << enemy->name << " has no skills! Skipping turn.\n";
                this_thread::sleep_for(chrono::seconds(1));
            }
        } else {
            if (enemy->isStunned) {
                cout << enemy->name << " is stunned and cannot act!" << endl;
                enemy->isStunned = false;
                this_thread::sleep_for(chrono::seconds(1));
            } else if (!enemy->skills.empty()) {
                int skillIndex = uniform_int_distribution<>(0, enemy->skills.size() - 1)(gen);
                if (enemy->isHealingDisabled && (enemy->skills[skillIndex].name == "Heal" || enemy->skills[skillIndex].name == "Haku Technique" || enemy->skills[skillIndex].name == "Soul Infiltration")) {
                    cout << enemy->name << "'s healing skills are disabled, this skill is ineffective!" << endl;
                    this_thread::sleep_for(chrono::seconds(1));
                } else {
                    enemy->skills[skillIndex].use(*enemy, player);
                    if (enemy->skills[skillIndex].name == "Shadow Burst") {
                        playerDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 1, "Shadow Burst", false});
                        player.attributes.defense -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Shadow Burst", -(5 + (currentLayer - 1) * 2), true});
                    } else if (enemy->skills[skillIndex].name == "Iron Shield") {
                        enemyDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Iron Shield", false});
                        enemy->attributes.defense += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["defense"].push_back({"Iron Shield", 10 + (currentLayer - 1) * 5, true});
                    } else if (enemy->skills[skillIndex].name == "Golden Slash") {
                        enemyDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Golden Slash", false});
                        enemy->attributes.critChance += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["critChance"].push_back({"Golden Slash", 10 + (currentLayer - 1) * 5, true});
                    } else if (enemy->skills[skillIndex].name == "Overload Pulse") {
                        playerDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 2, "Overload Pulse", false});
                        player.attributes.speed -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["speed"].push_back({"Overload Pulse", -(5 + (currentLayer - 1) * 2), true});
                    } else if (enemy->skills[skillIndex].name == "Juice Splash") {
                        playerArmorBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Juice Splash", false});
                        player.attributes.armor -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["armor"].push_back({"Juice Splash", -(10 + (currentLayer - 1) * 5), true});
                    } else if (enemy->skills[skillIndex].name == "Hellfire Storm") {
                        playerDefenseBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Hellfire Storm", false});
                        player.attributes.defense -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Hellfire Storm", -(10 + (currentLayer - 1) * 5), true});
                    } else if (enemy->skills[skillIndex].name == "Fireball Technique") {
                        int burnDamage = static_cast<int>(player.maxHealth * 0.3f);
                        playerBurnEffects.push_back({burnDamage, 3, "Fireball Technique"});
                    } else if (enemy->skills[skillIndex].name == "Haku Technique") {
                        int healAmount = static_cast<int>(enemy->maxHealth * 0.1f);
                        enemyHealEffects.push_back({healAmount, 3, "Haku Technique"});
                    }
                    this_thread::sleep_for(chrono::seconds(1));
                }
            } else {
                cout << enemy->name << " has no skills! Skipping turn.\n";
                this_thread::sleep_for(chrono::seconds(1));
            }

            if (player.attributes.health <= 0 && !player.handleFatalDamage()) {
                for (const auto& buff : playerDefenseBuffs) {
                    if (buff.source == "Soul Infiltration" && buff.value == 100) {
                        player.attributes.critChance -= buff.value;
                        cout << player.name << "'s " << buff.source << " critical rate effect removed, critical rate change -"
                             << abs(buff.value) << "!" << endl;
                    } else if (buff.source == "Soul Infiltration" && buff.value == 200) {
                        player.attributes.critDamage -= buff.value;
                        cout << player.name << "'s " << buff.source << " critical damage effect removed, critical damage change -"
                             << abs(buff.value) << "!" << endl;
                    } else {
                        player.attributes.defense -= buff.value;
                        if (buff.appliedByPlayer) {
                            cout << player.name << "'s " << buff.source << " defense effect removed, defense change "
                                 << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                        } else {
                            cout << player.name << "'s defense restored due to end of " << enemy->name << "'s " << buff.source
                                 << " effect, defense change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                                 << "!" << endl;
                        }
                    }
                }
                playerDefenseBuffs.clear();

                for (const auto& buff : playerArmorBuffs) {
                    player.attributes.armor -= buff.value;
                    if (buff.appliedByPlayer) {
                        cout << player.name << "'s " << buff.source << " armor effect removed, armor change "
                             << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                    } else {
                        cout << player.name << "'s armor restored due to end of " << enemy->name << "'s " << buff.source
                             << " effect, armor change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                             << "!" << endl;
                    }
                }
                playerArmorBuffs.clear();

                for (const auto& buff : enemyDefenseBuffs) {
                    enemy->attributes.defense -= buff.value;
                    if (buff.appliedByPlayer) {
                        cout << enemy->name << "'s defense restored due to end of " << player.name << "'s " << buff.source
                             << " effect, defense change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                             << "!" << endl;
                    } else {
                        cout << enemy->name << "'s " << buff.source << " defense effect removed, defense change "
                             << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                    }
                }
                enemyDefenseBuffs.clear();

                for (const auto& buff : enemyArmorBuffs) {
                    enemy->attributes.armor -= buff.value;
                    if (buff.appliedByPlayer) {
                        cout << enemy->name << "'s armor restored due to end of " << player.name << "'s " << buff.source
                             << " effect, armor change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                             << "!" << endl;
                    } else {
                        cout << enemy->name << "'s " << buff.source << " armor effect removed, armor change "
                             << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                    }
                }
                enemyArmorBuffs.clear();

                playerBurnEffects.clear();
                enemyBurnEffects.clear();
                playerHealEffects.clear();
                enemyHealEffects.clear();
                playerBleedEffects.clear();
                enemyBleedEffects.clear();

                auto& playerBonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                auto& enemyBonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                for (auto& [key, bonuses] : playerBonuses) {
                    bonuses.erase(std::remove_if(bonuses.begin(), bonuses.end(),
                        [](const Bonus& b) { return b.isTemporary; }), bonuses.end());
                }
                for (auto& [key, bonuses] : enemyBonuses) {
                    bonuses.erase(std::remove_if(bonuses.begin(), bonuses.end(),
                        [](const Bonus& b) { return b.isTemporary; }), bonuses.end());
                }

                cout << "You were defeated by " << enemy->name << "! Game over.\n";
                return false;
            }

            if (player.isStunned) {
                cout << player.name << " is stunned and cannot act!" << endl;
                player.isStunned = false;
                this_thread::sleep_for(chrono::seconds(1));
            } else if (!player.skills.empty()) {
                cout << "\nYour skills:\n";
                for (size_t i = 0; i < player.skills.size(); ++i) {
                    cout << i + 1 << ". " << player.skills[i].name << ": "
                         << player.skills[i].description << "\n";
                }
                cout << "Select a skill (enter number): ";
                int skillChoice;
                while (!(cin >> skillChoice) || skillChoice < 1 || skillChoice > static_cast<int>(player.skills.size())) {
                    cout << "Invalid input, please enter a valid skill number: ";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                }
                if (player.isHealingDisabled && (player.skills[skillChoice - 1].name == "Heal" || player.skills[skillChoice - 1].name == "Haku Technique" || player.skills[skillChoice - 1].name == "Soul Infiltration")) {
                    cout << player.name << "'s healing skills are disabled, this skill is ineffective!" << endl;
                    this_thread::sleep_for(chrono::seconds(1));
                } else {
                    player.skills[skillChoice - 1].use(player, *enemy);
                    if (player.skills[skillChoice - 1].name == "Heal") {
                        playerDefenseBuffs.push_back({5 + (currentLayer - 1) * 2, 2, "Heal", true});
                        player.attributes.defense += 5 + (currentLayer - 1) * 2;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Heal", 5 + (currentLayer - 1) * 2, true});
                    } else if (player.skills[skillChoice - 1].name == "Shadow Burst") {
                        enemyDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 1, "Shadow Burst", true});
                        enemy->attributes.defense -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["defense"].push_back({"Shadow Burst", -(5 + (currentLayer - 1) * 2), true});
                    } else if (player.skills[skillChoice - 1].name == "Iron Shield") {
                        playerDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Iron Shield", true});
                        player.attributes.defense += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["defense"].push_back({"Iron Shield", 10 + (currentLayer - 1) * 5, true});
                    } else if (player.skills[skillChoice - 1].name == "Golden Slash") {
                        playerDefenseBuffs.push_back({10 + (currentLayer - 1) * 5, 2, "Golden Slash", true});
                        player.attributes.critChance += 10 + (currentLayer - 1) * 5;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["critChance"].push_back({"Golden Slash", 10 + (currentLayer - 1) * 5, true});
                    } else if (player.skills[skillChoice - 1].name == "Overload Pulse") {
                        enemyDefenseBuffs.push_back({-(5 + (currentLayer - 1) * 2), 2, "Overload Pulse", true});
                        enemy->attributes.speed -= (5 + (currentLayer - 1) * 2);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["speed"].push_back({"Overload Pulse", -(5 + (currentLayer - 1) * 2), true});
                    } else if (player.skills[skillChoice - 1].name == "Juice Splash") {
                        enemyArmorBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Juice Splash", true});
                        enemy->attributes.armor -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["armor"].push_back({"Juice Splash", -(10 + (currentLayer - 1) * 5), true});
                    } else if (player.skills[skillChoice - 1].name == "Hellfire Storm") {
                        enemyDefenseBuffs.push_back({-(10 + (currentLayer - 1) * 5), 2, "Hellfire Storm", true});
                        enemy->attributes.defense -= (10 + (currentLayer - 1) * 5);
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["defense"].push_back({"Hellfire Storm", -(10 + (currentLayer - 1) * 5), true});
                    } else if (player.skills[skillChoice - 1].name == "Fireball Technique") {
                        int burnDamage = static_cast<int>(enemy->maxHealth * 0.3f);
                        enemyBurnEffects.push_back({burnDamage, 3, "Fireball Technique"});
                    } else if (player.skills[skillChoice - 1].name == "Haku Technique") {
                        int healAmount = static_cast<int>(player.maxHealth * 0.1f);
                        playerHealEffects.push_back({healAmount, 3, "Haku Technique"});
                    } else if (player.skills[skillChoice - 1].name == "Assault Thrust") {
                        enemyArmorBuffs.push_back({-(25 + static_cast<int>(enemy->attributes.armor * 0.3f)), 2, "Assault Thrust", true});
                        enemy->attributes.armor -= (25 + static_cast<int>(enemy->attributes.armor * 0.3f));
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
                        bonuses["armor"].push_back({"Assault Thrust", -(25 + static_cast<int>(enemy->attributes.armor * 0.3f)), true});
                    } else if (player.skills[skillChoice - 1].name == "Endless Bleeding") {
                        int bleedDamage = static_cast<int>(enemy->maxHealth * 0.2f);
                        enemyBleedEffects.push_back({bleedDamage, 3, "Endless Bleeding"});
                        enemy->isHealingDisabled = true;
                    } else if (player.skills[skillChoice - 1].name == "Soul Infiltration") {
                        playerDefenseBuffs.push_back({100, 2, "Soul Infiltration", true});
                        player.attributes.critChance += 100;
                        playerDefenseBuffs.push_back({200, 2, "Soul Infiltration", true});
                        player.attributes.critDamage += 200;
                        auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
                        bonuses["critChance"].push_back({"Soul Infiltration", 100, true});
                        bonuses["critDamage"].push_back({"Soul Infiltration", 200, true});
                    }
                    this_thread::sleep_for(chrono::seconds(1));
                }
            } else {
                cout << "You have no skills! Skipping your turn.\n";
                this_thread::sleep_for(chrono::seconds(1));
            }
        }

        if (enemy->attributes.health <= 0) {
            cout << enemy->name << " has been defeated!" << endl;
            player.onEnemyDefeated();
            break;
        }

        // Handle burn effects
        for (auto& effect : playerBurnEffects) {
            player.attributes.health = std::max(0, player.attributes.health - effect.damage);
            cout << player.name << " takes damage from " << effect.source << "'s burn effect, losing "
                 << effect.damage << " health (current health: " << player.attributes.health << "/" << player.maxHealth << ")!" << endl;
            effect.duration--;
            if (player.attributes.health <= 0 && !player.handleFatalDamage()) {
                cout << "You were defeated by " << enemy->name << "'s burn effect! Game over.\n";
                return false;
            }
        }
        playerBurnEffects.erase(std::remove_if(playerBurnEffects.begin(), playerBurnEffects.end(),
            [](const BurnEffect& e) { return e.duration <= 0; }), playerBurnEffects.end());

        for (auto& effect : enemyBurnEffects) {
            enemy->attributes.health = std::max(0, enemy->attributes.health - effect.damage);
            cout << enemy->name << " takes damage from " << effect.source << "'s burn effect, losing "
                 << effect.damage << " health (current health: " << enemy->attributes.health << "/" << enemy->maxHealth << ")!" << endl;
            effect.duration--;
            if (enemy->attributes.health <= 0) {
                cout << enemy->name << " was defeated by burn effect!" << endl;
                player.onEnemyDefeated();
                break;
            }
        }
        enemyBurnEffects.erase(std::remove_if(enemyBurnEffects.begin(), enemyBurnEffects.end(),
            [](const BurnEffect& e) { return e.duration <= 0; }), enemyBurnEffects.end());

        // Handle bleed effects
        for (auto& effect : playerBleedEffects) {
            player.attributes.health = std::max(0, player.attributes.health - effect.damage);
            cout << player.name << " takes damage from " << effect.source << "'s bleed effect, losing "
                 << effect.damage << " health (current health: " << player.attributes.health << "/" << player.maxHealth << ")!" << endl;
            effect.duration--;
            if (player.attributes.health <= 0 && !player.handleFatalDamage()) {
                cout << "You were defeated by " << enemy->name << "'s bleed effect! Game over.\n";
                return false;
            }
        }
        playerBleedEffects.erase(std::remove_if(playerBleedEffects.begin(), playerBleedEffects.end(),
            [](const BleedEffect& e) { return e.duration <= 0; }), playerBleedEffects.end());

        for (auto& effect : enemyBleedEffects) {
            enemy->attributes.health = std::max(0, enemy->attributes.health - effect.damage);
            cout << enemy->name << " takes damage from " << effect.source << "'s bleed effect, losing "
                 << effect.damage << " health (current health: " << enemy->attributes.health << "/" << enemy->maxHealth << ")!" << endl;
            effect.duration--;
            if (enemy->attributes.health <= 0) {
                cout << enemy->name << " was defeated by bleed effect!" << endl;
                player.onEnemyDefeated();
                break;
            }
        }
        enemyBleedEffects.erase(std::remove_if(enemyBleedEffects.begin(), enemyBleedEffects.end(),
            [](const BleedEffect& e) { return e.duration <= 0; }), enemyBleedEffects.end());

        // Handle continuous healing effects
        for (auto& effect : playerHealEffects) {
            player.heal(effect.amount);
            cout << player.name << " receives continuous healing from " << effect.source << ", restoring "
                 << effect.amount << " health (current health: " << player.attributes.health << "/" << player.maxHealth << ")!" << endl;
            effect.duration--;
        }
        playerHealEffects.erase(std::remove_if(playerHealEffects.begin(), playerHealEffects.end(),
            [](const HealEffect& e) { return e.duration <= 0; }), playerHealEffects.end());

        for (auto& effect : enemyHealEffects) {
            enemy->heal(effect.amount);
            cout << enemy->name << " receives continuous healing from " << effect.source << ", restoring "
                 << effect.amount << " health (current health: " << enemy->attributes.health << "/" << enemy->maxHealth << ")!" << endl;
            effect.duration--;
        }
        enemyHealEffects.erase(std::remove_if(enemyHealEffects.begin(), enemyHealEffects.end(),
            [](const HealEffect& e) { return e.duration <= 0; }), enemyHealEffects.end());

        // Update defense buffs/debuffs
        for (auto& buff : playerDefenseBuffs) {
            buff.duration--;
            if (buff.duration <= 0) {
                if (buff.source == "Soul Infiltration" && buff.value == 100) {
                    player.attributes.critChance -= buff.value;
                    cout << player.name << "'s " << buff.source << " critical rate effect ended, critical rate change -"
                         << abs(buff.value) << "!" << endl;
                } else if (buff.source == "Soul Infiltration" && buff.value == 200) {
                    player.attributes.critDamage -= buff.value;
                    cout << player.name << "'s " << buff.source << " critical damage effect ended, critical damage change -"
                         << abs(buff.value) << "!" << endl;
                } else {
                    player.attributes.defense -= buff.value;
                    if (buff.appliedByPlayer) {
                        cout << player.name << "'s " << buff.source << " defense effect ended, defense change "
                             << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                    } else {
                        cout << player.name << "'s defense restored due to end of " << enemy->name << "'s " << buff.source
                             << " effect, defense change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                             << "!" << endl;
                    }
                }
            }
        }
        playerDefenseBuffs.erase(std::remove_if(playerDefenseBuffs.begin(), playerDefenseBuffs.end(),
            [](const Buff& b) { return b.duration <= 0; }), playerDefenseBuffs.end());

        for (auto& buff : enemyDefenseBuffs) {
            buff.duration--;
            if (buff.duration <= 0) {
                enemy->attributes.defense -= buff.value;
                if (buff.appliedByPlayer) {
                    cout << enemy->name << "'s defense restored due to end of " << player.name << "'s " << buff.source
                         << " effect, defense change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                         << "!" << endl;
                } else {
                    cout << enemy->name << "'s " << buff.source << " defense effect ended, defense change "
                         << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                }
            }
        }
        enemyDefenseBuffs.erase(std::remove_if(enemyDefenseBuffs.begin(), enemyDefenseBuffs.end(),
            [](const Buff& b) { return b.duration <= 0; }), enemyDefenseBuffs.end());

        // Update armor buffs/debuffs
        for (auto& buff : playerArmorBuffs) {
            buff.duration--;
            if (buff.duration <= 0) {
                player.attributes.armor -= buff.value;
                if (buff.appliedByPlayer) {
                    cout << player.name << "'s " << buff.source << " armor effect ended, armor change "
                         << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                } else {
                    cout << player.name << "'s armor restored due to end of " << enemy->name << "'s " << buff.source
                         << " effect, armor change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                         << "!" << endl;
                }
            }
        }
        playerArmorBuffs.erase(std::remove_if(playerArmorBuffs.begin(), playerArmorBuffs.end(),
            [](const Buff& b) { return b.duration <= 0; }), playerArmorBuffs.end());

        for (auto& buff : enemyArmorBuffs) {
            buff.duration--;
            if (buff.duration <= 0) {
                enemy->attributes.armor -= buff.value;
                if (buff.appliedByPlayer) {
                    cout << enemy->name << "'s armor restored due to end of " << player.name << "'s " << buff.source
                         << " effect, armor change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                         << "!" << endl;
                } else {
                    cout << enemy->name << "'s " << buff.source << " armor effect ended, armor change "
                         << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
                }
            }
        }
        enemyArmorBuffs.erase(std::remove_if(enemyArmorBuffs.begin(), enemyArmorBuffs.end(),
            [](const Buff& b) { return b.duration <= 0; }), enemyArmorBuffs.end());

        cout << "\nPress Enter to continue the battle...\n";
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cin.get();
    }

    // Clean up effects
    for (const auto& buff : playerDefenseBuffs) {
        if (buff.source == "Soul Infiltration" && buff.value == 100) {
            player.attributes.critChance -= buff.value;
            cout << player.name << "'s " << buff.source << " critical rate effect removed, critical rate change -"
                 << abs(buff.value) << "!" << endl;
        } else if (buff.source == "Soul Infiltration" && buff.value == 200) {
            player.attributes.critDamage -= buff.value;
            cout << player.name << "'s " << buff.source << " critical damage effect removed, critical damage change -"
                 << abs(buff.value) << "!" << endl;
        } else {
            player.attributes.defense -= buff.value;
            if (buff.appliedByPlayer) {
                cout << player.name << "'s " << buff.source << " defense effect removed, defense change "
                     << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
            } else {
                cout << player.name << "'s defense restored due to end of " << enemy->name << "'s " << buff.source
                     << " effect, defense change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                     << "!" << endl;
            }
        }
    }
    playerDefenseBuffs.clear();

    for (const auto& buff : playerArmorBuffs) {
        player.attributes.armor -= buff.value;
        if (buff.appliedByPlayer) {
            cout << player.name << "'s " << buff.source << " armor effect removed, armor change "
                 << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
        } else {
            cout << player.name << "'s armor restored due to end of " << enemy->name << "'s " << buff.source
                 << " effect, armor change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                 << "!" << endl;
        }
    }
    playerArmorBuffs.clear();

    for (const auto& buff : enemyDefenseBuffs) {
        enemy->attributes.defense -= buff.value;
        if (buff.appliedByPlayer) {
            cout << enemy->name << "'s defense restored due to end of " << player.name << "'s " << buff.source
                 << " effect, defense change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                 << "!" << endl;
        } else {
            cout << enemy->name << "'s " << buff.source << " defense effect removed, defense change "
                 << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
        }
    }
    enemyDefenseBuffs.clear();

    for (const auto& buff : enemyArmorBuffs) {
        enemy->attributes.armor -= buff.value;
        if (buff.appliedByPlayer) {
            cout << enemy->name << "'s armor restored due to end of " << player.name << "'s " << buff.source
                 << " effect, armor change " << (buff.value > 0 ? "-" : "+") << abs(buff.value)
                 << "!" << endl;
        } else {
            cout << enemy->name << "'s " << buff.source << " armor effect removed, armor change "
                 << (buff.value > 0 ? "-" : "+") << abs(buff.value) << "!" << endl;
        }
    }
    enemyArmorBuffs.clear();

    playerBurnEffects.clear();
    enemyBurnEffects.clear();
    playerHealEffects.clear();
    enemyHealEffects.clear();
    playerBleedEffects.clear();
    enemyBleedEffects.clear();

    // Restore healing ability
    player.isHealingDisabled = false;
    enemy->isHealingDisabled = false;

    auto& playerBonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
    auto& enemyBonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(enemy->getAttributeBonuses());
    for (auto& [key, bonuses] : playerBonuses) {
        bonuses.erase(std::remove_if(bonuses.begin(), bonuses.end(),
            [](const Bonus& b) { return b.isTemporary; }), bonuses.end());
    }
    for (auto& [key, bonuses] : enemyBonuses) {
        bonuses.erase(std::remove_if(bonuses.begin(), bonuses.end(),
            [](const Bonus& b) { return b.isTemporary; }), bonuses.end());
    }

    // Ensure critical rate and critical damage from Soul Infiltration are properly removed
    player.attributes.critChance = std::max(0, player.attributes.critChance);
    player.attributes.critDamage = std::max(0, player.attributes.critDamage);

    // Unified health recovery logic
    if (player.attributes.health > 0) {
        player.attributes.health = player.maxHealth;
        cout << "Battle ended! Your health has been restored to maximum: " << player.attributes.health << "/" << player.maxHealth << "\n";
    }

    player.attributes.damageMultiplier = 1.0f;

    // Handle victory logic
    if (enemy->attributes.health <= 0) {
        cout << "Battle won! You defeated " << enemy->name << "!" << endl;
        player.attributes.damageMultiplier = 1.0f;
        int earnedGold = baseGoldDrop + static_cast<int>(gold * 0.1);
        gold += earnedGold;
        cout << "You gained " << earnedGold << " gold! Current gold: " << gold << endl;
        bool isBoss = (enemy->name == "Void Lord" || enemy->name == "Super Idol" || enemy->name == "Demon King");
        auto equipDrop = createEquipmentDrop(RoomType::ENEMY, isBoss);
        if (equipDrop) {
            player.addEquipment(*equipDrop);
        }
        this_thread::sleep_for(chrono::milliseconds(3000));
        return true;
    }

    if (player.attributes.speed > 10000) {
        return false;
    }
    // Handle case where player survives but fails (e.g., triggers Magic Shield)
    cout << "Battle ended, you survived!" << endl;
    this_thread::sleep_for(chrono::milliseconds(3000));
    return true;
}

void Dungeon::displayShop(Character& player) {
    vector<ShopItem> shopItems = {
        {"Refined Weapon", ShopItem::Type::EQUIPMENT, EquipmentType::WEAPON, 50, 0, 0},
        {"Refined Helmet", ShopItem::Type::EQUIPMENT, EquipmentType::HELMET, 30, 0, 0},
        {"Refined Armor", ShopItem::Type::EQUIPMENT, EquipmentType::ARMOR, 40, 0, 0},
        {"Health Potion", ShopItem::Type::HEALTH_POTION, EquipmentType::WEAPON, 20, 50, 0},
        {"Berserk Potion", ShopItem::Type::BERSERK_POTION, EquipmentType::WEAPON, 25, 0, 10}
    };

    random_device rd;
    mt19937 gen(rd());

    while (true) {
        auto currentItems = shopItems;
        shuffle(currentItems.begin(), currentItems.end(), gen);
        currentItems.resize(2);

        system(CLEAR);
        cout << "=== Shop ===\n";
        cout << "Your gold: " << gold << "\n";
        cout << "Your health: " << COLOR_RED << player.attributes.health << "/" << player.maxHealth << COLOR_RESET;
        auto bonuses = player.getAttributeBonuses();
        if (bonuses.count("health") && !bonuses.at("health").empty()) {
            cout << " (";
            bool first = true;
            for (const auto& bonus : bonuses.at("health")) {
                if (bonus.source != "Heal" && bonus.source != "Health Potion" && bonus.source != "Blood Attack") {
                    if (!first) cout << ", ";
                    cout << "+" << bonus.value << " " << bonus.source;
                    first = false;
                }
            }
            cout << ")";
        }
        cout << "\n";

        cout << "Available items:\n";
        for (size_t i = 0; i < currentItems.size(); ++i) {
            cout << i + 1 << ". " << currentItems[i].name << " (Price: " << currentItems[i].price << " gold)\n";
            if (currentItems[i].type == ShopItem::Type::EQUIPMENT) {
                cout << "   - Equipment: " << (currentItems[i].equipType == EquipmentType::WEAPON ? "Weapon" :
                                       currentItems[i].equipType == EquipmentType::HELMET ? "Helmet" :
                                       currentItems[i].equipType == EquipmentType::ARMOR ? "Armor" : "Unknown") << "\n";
            } else if (currentItems[i].type == ShopItem::Type::HEALTH_POTION) {
                cout << "   - Base effect: Restores " << currentItems[i].healthBonus << " health, increases with equipment level\n";
            } else if (currentItems[i].type == ShopItem::Type::BERSERK_POTION) {
                cout << "   - Base effect: Increases " << currentItems[i].attackBonus << " attack, increases with weapon level\n";
            }
        }
        cout << currentItems.size() + 1 << ". Leave shop\n";
        cout << "Enter your choice (1-" << currentItems.size() + 1 << "): ";

        int choice;
        while (!(cin >> choice) || choice < 1 || choice > static_cast<int>(currentItems.size()) + 1) {
            cout << "Invalid input, please enter a number between 1 and " << currentItems.size() + 1 << ": ";
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        if (choice == static_cast<int>(currentItems.size()) + 1) {
            cout << "You left the shop.\n";
            this_thread::sleep_for(chrono::milliseconds(2000));
            break;
        }

        const auto& item = currentItems[choice - 1];
        if (gold < item.price) {
            cout << "Insufficient gold! Need " << item.price << " gold, you have " << gold << " gold.\n";
            cout << "Press Enter to continue...\n";
            cin.get();
            continue;
        }

        gold -= item.price;
        if (item.type == ShopItem::Type::EQUIPMENT) {
            auto equip = std::make_unique<Equipment>(item.name, "Shop-purchased equipment", item.equipType);
            player.addEquipment(*equip);
            cout << "You purchased and equipped " << item.name << "!\n";
        } else if (item.type == ShopItem::Type::HEALTH_POTION) {
            player.heal(item.healthBonus);
            player.maxHealth += item.healthBonus;
            player.attributes.health = player.maxHealth;
            cout << "You purchased a Health Potion, increasing health cap by " << item.healthBonus << "! Current health: " << player.attributes.health << "/" << player.maxHealth << "\n";
        } else if (item.type == ShopItem::Type::BERSERK_POTION) {
            player.attributes.attack += item.attackBonus;
            auto& bonuses = const_cast<std::map<std::string, std::vector<Bonus>>&>(player.getAttributeBonuses());
            bonuses["attack"].push_back({"Berserk Potion", item.attackBonus});
            cout << "You purchased a Berserk Potion, attack increased by " << item.attackBonus << "! Current attack: " << player.attributes.attack << "\n";
        }
        cout << "Current gold: " << gold << "\n";
        cout << "Press Enter to continue...\n";
        cin.get();
    }
}

void Dungeon::explore() {
    if (!player) {
        cerr << "Error: Player pointer is null.\n";
        return;
    }
    if (layers.empty()) {
        cerr << "Error: Dungeon layers are empty.\n";
        return;
    }

    int currentRoomId = 1;
    int roomsPerLayer = layers[0].size();
    int bossRoomId = roomsPerLayer;
    bool showCharacterInfo = false;

    auto& firstLayerRooms = layers[0];
    auto firstRoomIt = find_if(firstLayerRooms.begin(), firstLayerRooms.end(),
                               [](const Room& r) { return r.id == 1; });
    if (firstRoomIt != firstLayerRooms.end()) {
        firstRoomIt->visited = true;
        cout << "Initialized Layer 1 Room 1 as visited" << endl;
    }

    for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex) {
        currentLayer = layerIndex + 1; // Update current layer
        cout << "\n=== Entering Layer " << currentLayer << " ===\n";
        currentRoomId = 1;
        auto& currentLayerRooms = layers[layerIndex];
        auto firstRoomIt = find_if(currentLayerRooms.begin(), currentLayerRooms.end(),
                                   [](const Room& r) { return r.id == 1; });
        if (firstRoomIt != currentLayerRooms.end()) {
            firstRoomIt->visited = true;
        }

        while (true) {
            auto displayDungeonInterface = [&]() {
                system(CLEAR);
                displayDungeonMap(layerIndex, currentRoomId); // Added call to displayDungeonMap
                auto& currentLayerRooms = layers[layerIndex];
                auto it = find_if(currentLayerRooms.begin(), currentLayerRooms.end(),
                                  [currentRoomId](const Room& r) { return r.id == currentRoomId; });
                if (it == currentLayerRooms.end()) {
                    cout << "Error: Room " << currentRoomId << " not found\n";
                    return false;
                }

                Room& currentRoom = *it;
                cout << "\n=== Layer " << currentLayer << " ===\n";
                cout << "You are currently in " << currentRoom.getTypeName() << " (ID: " << currentRoom.id << ")\n";
                cout << "Your health: " << COLOR_RED << player->attributes.health << "/" << player->maxHealth << COLOR_RESET;
                auto bonuses = player->getAttributeBonuses();
                if (bonuses.count("health") && !bonuses.at("health").empty()) {
                    cout << " (";
                    bool first = true;
                    for (const auto& bonus : bonuses.at("health")) {
                        if (bonus.source != "Heal" && bonus.source != "Health Potion" && bonus.source != "Blood Attack") {
                            if (!first) cout << ", ";
                            cout << "+" << bonus.value << " " << bonus.source;
                            first = false;
                        }
                    }
                    cout << ")";
                }
                cout << "\n";

                cout << "Your gold: " << gold << "\n";

                cout << "\nAccessible rooms: ";
                for (int conn : currentRoom.neighbors) {
                    auto connIt = find_if(currentLayerRooms.begin(), currentLayerRooms.end(),
                                          [conn](const Room& r) { return r.id == conn; });
                    if (connIt != currentLayerRooms.end()) {
                        cout << conn << " (" << connIt->getTypeName() << ") ";
                    } else {
                        cout << conn << " (Invalid Room ID) ";
                    }
                }
                cout << "\n";

                if (showCharacterInfo) {
                    cout << "\n--- Your Information ---" << endl;
                    if (!player) {
                        cerr << "Error: Player pointer became null before displaying info\n";
                        return false;
                    }
                    player->displayInfo();
                }
                return true;
            };

            if (!displayDungeonInterface()) return;

            auto& currentLayerRooms = layers[layerIndex];
            auto it = find_if(currentLayerRooms.begin(), currentLayerRooms.end(),
                              [currentRoomId](const Room& r) { return r.id == currentRoomId; });
            if (it == currentLayerRooms.end()) {
                cerr << "Error: Room " << currentRoomId << " not found\n";
                return;
            }
            Room& currentRoom = *it;
            bool wasVisited = currentRoom.visited;
            currentRoom.visited = true;

            if (currentRoom.type == RoomType::REWARD) {
                cout << "\nYou entered a mysterious shop!\n";
                displayShop(*player);
                if (!displayDungeonInterface()) return;
            } else if (currentRoom.type == RoomType::ENEMY && !wasVisited) {
                cout << "Entering battle room, type: Enemy\n";
                int baseGoldDrop;
                auto enemy = createEnemyForRoom(currentRoom.type, baseGoldDrop, currentLayer);
                if (enemy) {
                    bool playerWon = fight(*player, std::move(enemy), baseGoldDrop);
                    if (!playerWon) {
                        cout << "Player failed, returning to main menu\n";
                        cout << "Press Enter to return to main menu...\n";
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                        cin.get();
                        return;
                    }
                    cout << "Battle won, current layer: " << currentLayer << ", current room ID: " << currentRoomId << endl;
                    if (!displayDungeonInterface()) return;
                } else {
                    cout << "Error: Failed to create enemy, cannot enter battle\n";
                    this_thread::sleep_for(chrono::milliseconds(3000));
                    if (!displayDungeonInterface()) return;
                }
            } else if (currentRoom.type == RoomType::BOSS && !wasVisited) {
                cout << "Entering battle room, type: Boss\n";
                int baseGoldDrop;
                auto enemy = createEnemyForRoom(currentRoom.type, baseGoldDrop, currentLayer);
                if (enemy) {
                    bool playerWon = fight(*player, std::move(enemy), baseGoldDrop);
                    if (!playerWon) {
                        cout << "Player failed, returning to main menu\n";
                        cout << "Press Enter to return to main menu...\n";
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                        cin.get();
                        return;
                    }
                    cout << "Boss battle won, checking layer transition, current layer: " << currentLayer << endl;
                    if (layerIndex < numLayers - 1) {
                        cout << "\nYou defeated the Boss and entered the next layer!\n";
                        selectTalent(*player, currentLayer + 1);
                        this_thread::sleep_for(chrono::milliseconds(3000));
                        break; // Exit current layer loop, proceed to next layer
                    } else {
                        system(CLEAR);
                        cout << "==============================\n";
                        cout << "         Congratulations, you cleared the game!\n";
                        cout << "==============================\n";
                        cout << "Thank you for playing! Press Enter to return to main menu...\n";
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                        cin.get();
                        return;
                    }
                } else {
                    cout << "Error: Failed to create enemy, cannot enter battle\n";
                    this_thread::sleep_for(chrono::milliseconds(3000));
                    if (!displayDungeonInterface()) return;
                }
            } else if (currentRoom.type == RoomType::START && !wasVisited) {
                cout << "\nThis is the starting point of your adventure!\n";
                this_thread::sleep_for(chrono::milliseconds(3000));
                if (!displayDungeonInterface()) return;
            }

            cout << "\nEnter the room ID to proceed to (enter 0 to toggle character info display): ";
            int choice;
            while (!(cin >> choice)) {
                cout << "Invalid input, please enter a number (enter 0 to toggle character info display): ";
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
            }

            if (choice == 0) {
                showCharacterInfo = !showCharacterInfo;
                cout << "Character info display " << (showCharacterInfo ? "enabled" : "disabled") << "!\n";
                continue;
            }

            bool validChoice = false;
            for (int neighbor : currentRoom.neighbors) {
                if (choice == neighbor) {
                    validChoice = true;
                    break;
                }
            }

            if (!validChoice) {
                cout << "Invalid room ID!\n";
                this_thread::sleep_for(chrono::milliseconds(3000));
                continue;
            }

            if (choice == bossRoomId && !isLayerExplored(layerIndex)) {
                cout << "You must explore all other rooms on this layer (1-4, excluding the shop) before entering the Boss room!\n";
                this_thread::sleep_for(chrono::milliseconds(3000));
                continue;
            }

            cout << "Selected room ID: " << choice << endl;
            currentRoomId = choice;
        }
    }
    cout << "Adventure ended!\n";
}

void Dungeon::displayDungeonMap(int layerIndex, int currentRoomId) const {
    if (layerIndex < 0 || layerIndex >= static_cast<int>(layers.size())) {
        std::cerr << "Error: Invalid layer index " << layerIndex << std::endl;
        return;
    }

    const auto& currentLayer = layers[layerIndex];
    std::cout << "\n=== Layer " << layerIndex + 1 << " Dungeon Map ===\n";

    // Find the maximum room ID to determine the grid size
    int maxRoomId = 0;
    for (const auto& room : currentLayer) {
        maxRoomId = std::max(maxRoomId, room.id);
    }

    // Create a vector to store connections for easy lookup
    std::vector<std::vector<int>> connections(maxRoomId + 1);
    for (const auto& room : currentLayer) {
        for (int neighbor : room.neighbors) {
            if (neighbor > room.id) { // Avoid duplicate connections
                connections[room.id].push_back(neighbor);
            }
        }
    }

    // Print the map using ASCII art
    for (int i = 1; i <= maxRoomId; ++i) {
        auto it = std::find_if(currentLayer.begin(), currentLayer.end(),
                               [i](const Room& r) { return r.id == i; });
        if (it == currentLayer.end()) continue;

        const Room& room = *it;
        std::string roomLabel = std::to_string(room.id) + " (" + room.getTypeName() + ")";
        if (room.id == currentRoomId) {
            roomLabel = COLOR_GREEN + roomLabel + COLOR_RESET;
        }

        // Print room node
        std::cout << roomLabel;

        // Print connections to higher-numbered rooms
        bool hasConnections = false;
        for (int neighbor : connections[i]) {
            std::cout << " --- " << neighbor;
            hasConnections = true;
        }

        if (!hasConnections) {
            std::cout << " (No connections)";
        }
        std::cout << "\n";
    }

    // Print a legend for clarity
    std::cout << "\nLegend:\n";
    std::cout << "- Green highlighted room is your current location\n";
    std::cout << "- Numbers indicate room IDs, with room types in parentheses\n";
    std::cout << "- '---' indicates connections between rooms\n";
    std::cout << "==============================\n";
}